
#include <stddef.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>
/* Driver configuration */
#include "ti_drivers_config.h"
#include "SPIRAM.h"

#define TAG "SPIRAM"
#ifndef DEBUG_PRINT_ENABLE
#define DEBUG_PRINT_ENABLE 0
#endif
#if DEBUG_PRINT_ENABLE
#define DEBUG_PRINT(fmt, ...) \
    Display_printf(display, 0, 0, "[%s:%d] " fmt, TAG, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...)
#endif

#define SPIRAMSTACKSIZE 2048

SPI_Handle controllerSpi;
SPI_Params spiParams;
SPI_Transaction transaction;

char RecADCBUFF[QUEUED_ADC_MESSAGE_SIZE];

//char msg[3] = {0,1,2};
 
VTI7064BUF st_vti7064;

void SPIRAM_Init(void)
{
     /* Open SPI as controller (default) */
    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL1_PHA1;
    /* See device-specific technical reference manual for supported speeds */
    spiParams.bitRate     = 12000000;
    controllerSpi         = SPI_open(CONFIG_SPI_SRAM, &spiParams);
    if (controllerSpi == NULL)
    {
        DEBUG_PRINT( "Error initializing controller SPI\n");
        while (1) {}
    }
    else
    {
        DEBUG_PRINT( "Controller SPI initialized\n");
    }
    transaction.txBuf = (void *)st_vti7064.SendBUF;
    transaction.rxBuf = (void *)st_vti7064.ReadBUF;
}
static uint32_t ReadID(void)
{
    bool transferOK;
    st_vti7064.SendBUF[0] = VTI7064_JedecDeviceID;
    st_vti7064.SendBUF[1] = 0;
    st_vti7064.SendBUF[2] = 0;
    st_vti7064.SendBUF[3] = 0;
    transaction.count = VTI7064_SENDMINLEN + VTI7064_DEVICEIDLEN;

   // transaction.txBuf = (void *)st_vti7064.SendBUF;
    //transaction.rxBuf = (void *)st_vti7064.ReadBUF;
    
    transferOK = SPI_transfer(controllerSpi, &transaction);
    if (transferOK)
    {
    //    DEBUG_PRINT( "Controller received: %s", st_vti7064.ReadBUF);
    }
    else
    {
    //    DEBUG_PRINT( "Unsuccessful controller SPI transfer");
    }

    return (st_vti7064.ReadBUF[4] + st_vti7064.ReadBUF[5] * 256 + st_vti7064.ReadBUF[6] * 65536);
}

static bool Write_SRAM(uint32_t addr,char *data,uint32_t datalen)
{
    bool transferOK;
    uint16_t cnt;
    st_vti7064.SendBUF[0] = VTI7064_PageProgram;
    st_vti7064.SendBUF[1] = (uint8_t)(addr>>16);
    st_vti7064.SendBUF[2] = (uint8_t)(addr>>8);
    st_vti7064.SendBUF[3] = (uint8_t)(addr);
    for(cnt=0;cnt<datalen;cnt++)
    {
        st_vti7064.SendBUF[cnt + VTI7064_SENDMINLEN] = data[cnt];
    }
    transaction.count = datalen + VTI7064_SENDMINLEN;
    //strncpy((char *)&st_vti7064.SendBUF[VTI7064_SENDMINLEN], data, datalen);

    transferOK = SPI_transfer(controllerSpi, &transaction);
    if (transferOK)
    {
    //    DEBUG_PRINT( "Controller received: %s", st_vti7064.ReadBUF);
        return true;
    }
    else
    {
    //    DEBUG_PRINT( "Unsuccessful controller SPI transfer");
        return false;
    }
}

bool Read_SRAM(uint32_t addr,uint32_t datalen)
{
    bool transferOK;
    st_vti7064.SendBUF[0] = VTI7064_ReadData;
    st_vti7064.SendBUF[1] = (uint8_t)(addr>>16);
    st_vti7064.SendBUF[2] = (uint8_t)(addr>>8);
    st_vti7064.SendBUF[3] = (uint8_t)(addr);
    for(uint16_t i = 0;i<datalen;i++)
    {
        st_vti7064.SendBUF[i+4] = 0xff;
    }
    transaction.count = datalen + VTI7064_SENDMINLEN;

    transferOK = SPI_transfer(controllerSpi, &transaction);
    if (transferOK)
    {
    //    DEBUG_PRINT( "Controller received: %s", st_vti7064.ReadBUF);
        return true;
    }
    else
    {
    //    DEBUG_PRINT( "Unsuccessful controller SPI transfer");
        return false;
    }
}

uint8_t* Read_OverLengthData(uint16_t Count,uint16_t *datalen)
{
    bool transferOK;
    uint32_t addr = Count * ADCSAMPLESIZE;
    st_vti7064.SendBUF[0] = VTI7064_ReadData;
    st_vti7064.SendBUF[1] = (uint8_t)(addr>>16);
    st_vti7064.SendBUF[2] = (uint8_t)(addr>>8);
    st_vti7064.SendBUF[3] = (uint8_t)(addr);
    for(uint16_t i = 0;i < ADCSAMPLESIZE; i++)
    {
        st_vti7064.SendBUF[i+4] = 0xff;
    }
    transaction.count = ADCSAMPLESIZE + VTI7064_SENDMINLEN;

    transferOK = SPI_transfer(controllerSpi, &transaction);
    if (transferOK)
    {
        if(Count == 0){
            st_vti7064.ReadBUF[2] = (uint8_t)(OverLenrth_Zdata & 0xff);//设置数据类型为超长数据
            st_vti7064.ReadBUF[3] = (uint8_t)((OverLenrth_Zdata>>8) & 0xff);

            *datalen = ADCSAMPLESIZE + 2;//首包多发送2byte

            return &st_vti7064.ReadBUF[2];
        }
        else {
            *datalen = ADCSAMPLESIZE;
            return &st_vti7064.ReadBUF[4];
        }
    }
    else
    {
    //    DEBUG_PRINT( "Unsuccessful controller SPI transfer");
        return NULL;
    }
}

uint32_t readid;

void *SPI_ADCBUFFToSRAM(void *arg0)
{
    mqd_t queueReceive;
    struct mq_attr attr;
    uint32_t count = 0;
    uint32_t msg_prio=0;
    SPIRAM_Init();
    readid = ReadID();
    attr.mq_flags   = 0;
    attr.mq_maxmsg  = MAX_QUEUED_ADC_CONVERSIONS;
    attr.mq_msgsize = QUEUED_ADC_MESSAGE_SIZE;
    attr.mq_curmsgs = 0;
    queueReceive = mq_open("ADCBuf", O_RDWR, 0664, &attr);
    st_vti7064.WriteAddr = 0;
    //SPIRAM_TEST();
    for(;;)
    {
        //Write_SRAM(0,msg,3);
       // Read_SRAM(0,3);
        mq_receive(queueReceive, (char *)RecADCBUFF, QUEUED_ADC_MESSAGE_SIZE, &msg_prio);
        if(msg_prio == 1)
        {
            Write_SRAM(count * QUEUED_ADC_MESSAGE_SIZE,RecADCBUFF,QUEUED_ADC_MESSAGE_SIZE);
            count++;
        }
        else if(msg_prio == 0){//结束任务
            break;
        }
        //sleep(1);
        /*if(count == 2)
        {
            Read_SRAM(512,512);
        }*/
    }
    SPI_close(controllerSpi);//关闭spi，保证休眠功耗
   // Task_exit();
    return (NULL);
}

void adctoram_task(UArg arg0, UArg arg1)
{
    mqd_t queueReceive;
    struct mq_attr attr;
    uint32_t count = 0;
    uint32_t msg_prio=0;
    SPIRAM_Init();
    readid = ReadID();
    attr.mq_flags   = 0;
    attr.mq_maxmsg  = MAX_QUEUED_ADC_CONVERSIONS;
    attr.mq_msgsize = QUEUED_ADC_MESSAGE_SIZE;
    attr.mq_curmsgs = 0;
    queueReceive = mq_open("ADCBuf", O_RDWR, 0664, &attr);
    st_vti7064.WriteAddr = 0;
    //SPIRAM_TEST();
    for(;;)
    {
        //Write_SRAM(0,msg,3);
       // Read_SRAM(0,3);
        mq_receive(queueReceive, (char *)RecADCBUFF, QUEUED_ADC_MESSAGE_SIZE, &msg_prio);
        if(msg_prio == 1)
        {
            Write_SRAM(count * QUEUED_ADC_MESSAGE_SIZE,RecADCBUFF,QUEUED_ADC_MESSAGE_SIZE);
            count++;
        }
        else if(msg_prio == 0){//结束任务
            break;
        }
        //sleep(1);
        /*if(count == 2)
        {
            Read_SRAM(512,512);
        }*/
    }
    SPI_close(controllerSpi);//关闭spi，保证休眠功耗
    mq_close(queueReceive);
    sem_post(&exitSavetask);
    Task_exit();
}

void SPIRAM_Task(Void)
{
    Task_Handle tasksample;
    Task_Params taskParams;
    Task_Params_init(&taskParams);
    taskParams.stackSize = SPIRAMSTACKSIZE; // 需要更大的栈空间
    taskParams.priority = 2; // 较低优先级
    //taskParams.arg0 = (UArg)mode;   // 第一个参数
    tasksample = Task_create(adctoram_task, &taskParams, NULL);
    sem_wait(&exitSavetask);//等待存储结束
    Task_delete(&tasksample);
}

void SPIRAM_ThreadStart(void)
{
    pthread_t thread;
    pthread_attr_t attrs;
    struct sched_param priParam;
    int retc;

     pthread_attr_init(&attrs);

    /* Set priority, detach state, and stack size attributes */
    priParam.sched_priority = 2;
    retc  = pthread_attr_setschedparam(&attrs, &priParam);
    retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
    retc |= pthread_attr_setstacksize(&attrs, SPIRAMSTACKSIZE);
    if (retc != 0)
    {
        /* failed to set attributes */
        while (1) {}
    }

    retc = pthread_create(&thread, &attrs, SPI_ADCBUFFToSRAM, NULL);
    if (retc != 0)
    {
        /* pthread_create() failed */
        while (1) {}
    }
}

